package bancosys.tec.query.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import bancosys.tec.persist.hibernate.PartitionSessionFactory;
import bancosys.tec.persist.hibernate.page.PagingService;
import bancosys.tec.query.QueryParameter;
import bancosys.tec.query.exception.QueryParameterException;

/**
 * @author frank
 * @deprecated nao usar. Fazer queries com HQL ou Criteria
 */
@Deprecated
@SuppressWarnings("unchecked")
public class BaseQueryParameter implements QueryParameter {

    private Object bo;

    // private final List<Criterion> expressions = new ArrayList<Criterion>();

    private final List expressions = new ArrayList();

    // private final List<Order> orders = new ArrayList<Order>();
    private final List orders = new ArrayList();

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.query.QueryParameter#executeQuery(org.hibernate.Session)
     */
    public List executeQuery(Session session) throws QueryParameterException {
        Criteria crit = session.createCriteria(this.bo.getClass());
        for (Iterator it = this.expressions.iterator(); it.hasNext();) {
            Criterion expression = (Criterion) it.next();
            crit.add(expression);
        }
        for (Iterator it = this.orders.iterator(); it.hasNext();) {
            Order order = (Order) it.next();
            crit.addOrder(order);
        }
        this.paginateCriteria(session, crit);
        try {
            List list = crit.list();
            return list;
        } catch (HibernateException e) {
            throw new QueryParameterException(e);
        }
    }

    /**
     * @param session {@link Session}
     * @param crit {@link Criteria}
     */
    private void paginateCriteria(Session session, Criteria crit) {
        SessionFactory sessionFactory = session.getSessionFactory();
        if (sessionFactory instanceof PartitionSessionFactory) {
            PartitionSessionFactory partitionSessionFactory = (PartitionSessionFactory) sessionFactory;
            PagingService pagingService = partitionSessionFactory.getPagingService();
            if (pagingService != null) {
                pagingService.paginate(crit);
            }
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.query.QueryParameter#setBean(java.lang.Object)
     */
    public void setBean(Object obj) {
        // TODO Auto-generated method stub
    }

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.query.QueryParameter#addBO(java.lang.Object)
     */
    public void addBO(Object aBO) {
        this.bo = aBO;
    }

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.query.QueryParameter#addBetween(java.lang.String, java.lang.Object, java.lang.Object)
     */
    public void addBetween(String property, Object valueSt, Object valueEnd) {
        this.expressions.add(Restrictions.between(property, valueSt, valueEnd));
    }

    /**
     * Adiciona uma ordenacao a pesquisa. Em ordenacao decrescente por padrao.
     * 
     * @param property campo a ser usado para ordenacao.
     * @return devolve o proprio objeto pra poder ser usado de forma encadeada (eg. foo.addOrderBy(...).addOrderBy(...))
     */
    public QueryParameter addOrderBy(String property) {
        this.addOrderBy(property, true);
        return this;
    }

    /**
     * Adiciona uma ordenacao a pesquisa. Podendo escolher se crescente ou decrescente.
     * 
     * @param property campo a ser usado para ordenacao.
     * @param desc <code>true</code> para decrescente, <code>false</code> para crescente.
     * @return devolve o proprio objeto pra poder ser usado de forma encadeada (eg. foo.addOrderBy(...).addOrderBy(...))
     */
    public QueryParameter addOrderBy(String property, boolean desc) {
        if (desc) {
            this.orders.add(Order.desc(property));
        } else {
            this.orders.add(Order.asc(property));
        }
        return this;
    }

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.query.QueryParameter#addPropertyForExpression(java.lang.String, java.lang.Object, int)
     */
    public void addPropertyForExpression(String property, Object value, int expression) {
        if (QueryParameter.EXPRESSION_EQUAL == expression) {
            this.expressions.add(Restrictions.eq(property, value));
        } else if (QueryParameter.EXPRESSION_LIKE == expression) {
            this.expressions.add(Restrictions.like(property, "%" + value + "%"));
        } else if (QueryParameter.EXPRESSION_NOT_EQUALS == expression) {
            this.expressions.add(Restrictions.ne(property, value));
        } else if (QueryParameter.EXPRESSION_GREATER_OR_EQUAL == expression) {
            this.expressions.add(Restrictions.ge(property, value));
        } else if (QueryParameter.EXPRESSION_LESS_OR_EQUAL == expression) {
            this.expressions.add(Restrictions.le(property, value));
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.query.QueryParameter#addIn(java.lang.String, java.lang.Object[])
     */
    public void addIn(String property, Object[] values) {
        this.expressions.add(Restrictions.in(property, values));
    }
}